﻿using RaptorEngine;
using OilRigSumoWrestlers.Controllables.Controllers;
using Microsoft.Xna.Framework;
using OilRigSumoWrestlers.Levels;

namespace OilRigSumoWrestlers.Artificial_intelligence
{
    /// <summary>
    /// A behavior for the AI focused on attacking the current enemy
    /// </summary>
    class AttackBehavior : Behavior
    {
        private GameTime _gameTime;
        //Avoid variables used to make the AI commit to avoiding obstacles for a
        //certain time to prevent hysteria
        private int _avoidCount = 0;
        private Vector2 _avoidDirection;

        public AttackBehavior(Entity agent, Entity enemy, PlayerControllable controllable, ALevel level)
            : base(agent, enemy, controllable, level)
        {

        }

        public override void Update(GameTime gameTime)
        {
            _gameTime = gameTime;

            Move();
        }

        private void Move()
        {
            //Avoid obstacles if commited to avoiding or if getting close to an obstacle
            if (_avoidCount > 0
                || AIHelper.IsPathObstructed(level.GetIndexAtPosition(agent.Position),
                level.GetIndexAtPosition(agent.Position + agentMovable.Velocity * GameConstant.AI_EVADE_TENDENCY)
                , level))
            {
                if (_avoidCount == 0)
                    _avoidDirection = GetAvoidDirection(_gameTime);

                if (_avoidCount >= GameConstant.AI_AVOID_TIME)
                    _avoidCount = 0;
                else
                    _avoidCount += _gameTime.ElapsedGameTime.Milliseconds;

                agentControllable.Move(new Vector2(_avoidDirection.Y, _avoidDirection.X), _gameTime);
            }
            else
            {
                AttackOpponent();
            }
        }

        private void AttackOpponent()
        {
            //predict where the enemy should be next to try and intercept
            Vector3 direction = enemy.Position + enemyMovable.Velocity * GameConstant.AI_ATTACK_PREDICTION_MODIFIER * DistanceToEnemy - agent.Position;
            direction.Normalize();
            agentControllable.Move(new Vector2(direction.Z, direction.X), _gameTime);

            //push the enemy if you have run into him
            if (DistanceToEnemy > GameConstant.AI_MIN_PUSH_DIST && DistanceToEnemy
                < GameConstant.AI_MAX_PUSH_DIST && !ApproachingEnemy
                && GameEngine.Instance.Random.NextDouble() < GameConstant.AI_PUSH_CHANCE)
            {
                agentControllable.Push(_gameTime);
            }
        }

        public override string ToString()
        {
            return "Attack";
        }
    }
}
